-- The MIT License
-- 
-- Copyright (c) 2008 Matthew Maravillas, Patrick Quinn
-- 
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
-- 
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
-- 
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-- THE SOFTWARE.

local KothOptions = import('/mods/koth/hook/lua/kothOptions.lua')
local UIUtil = import('/lua/ui/uiutil.lua')
local LayoutHelpers = import('/lua/maui/layouthelpers.lua')
local MenuCommon = import('/lua/ui/menus/menucommon.lua')
local Bitmap = import('/lua/maui/bitmap.lua').Bitmap
local PauseGame = import('/lua/ui/game/options.lua').PauseGame
local Tooltip = import('/lua/ui/game/tooltip.lua')
local Grid = import('/lua/maui/grid.lua').Grid
local Combo = import('/lua/ui/controls/combo.lua').Combo
local Group = import('/lua/maui/group.lua').Group
local Tooltips = import('/lua/ui/help/tooltips.lua').Tooltips
local UserPlayerQuery = import('/lua/UserPlayerQuery.lua')

local OPTION_CHANGED_QUERY_NAME = "KothOptionChanged"
local OPTIONS_DISMISSED_QUERY_NAME = "KothOptionsDismissed"

local selectedOptions = KothOptions.KothOptions
local dialogControls = { }

-- TODO: Put this function somewhere else
function IsHost()
    local clients = GetSessionClients()
    local uidZeroExists = false
    
    for index, client in clients do
        if client['local'] and client.uid == "0" then
            return true
        elseif client.uid == "0" then
            uidZeroExists = true
        end
    end
    
    if not uidZeroExists then
        ERROR('IsHost: Could not find player with UID 0! KotH options will not be selectable.')
    end
    
    return false
end

function BroadcastOptionChange(optionKey, newValue)
    -- We only need to send one query out, since all players receive all queries
    local queryData = {
        From = GetFocusArmy(),
        To = GetFocusArmy(),
        Name = OPTION_CHANGED_QUERY_NAME,
        Key = optionKey,
        Value = newValue,
    }
    LOG('BroadcastOptionChange: Sending query: ' .. repr(queryData))
    UserPlayerQuery.Query(queryData)
end

function CreateOptionLabel(parent, option)
    local label = UIUtil.CreateText(parent, option.title, 14, "Arial")
    
    label.HandleEvent = function(self, event)
        if event.Type == 'MouseEnter' then
            Tooltip.CreateMouseoverDisplay(self, 'koth_' .. option.key, .5, true)
        elseif event.Type == 'MouseExit' then
            Tooltip.DestroyMouseoverDisplay()
        end
    end
    
    Tooltips['koth_' .. option.key] = { title = option.title, description = option.tooltip }
    
    return label
end

function CreateValueComboBox(parent, option)
    local combo = Combo(parent, nil, nil, nil, nil, "UI_Tab_Rollover_01", "UI_Tab_Click_01")

    combo.Width:Set(240)
    combo.Depth:Set(function() return parent.Depth() + 10 end)
    
    local items = { }
    local tooltips = { }
    local selected = option.default or 1
    
    combo.keyMap = { }
    
    for index, choice in option.choices do
        items[index] = choice.text
        combo.keyMap[choice.key] = index

        tooltips[index] = 'koth_' .. option.key .. '_' .. choice.key
        Tooltips[tooltips[index]] = { title = choice.text, description = choice.tooltip }
        
        if selectedOptions[option.key] == choice.key then
            selected = index
        end
    end
    
    combo:AddItems(items, selected)
    
    combo.OnClick = function(self, index, text, skipUpdate)
        self.Key = index
        selectedOptions[option.key] = option.choices[index].key
        BroadcastOptionChange(option.key, selectedOptions[option.key])
    end
    
    Tooltip.AddComboTooltip(combo, tooltips, combo._list)    
    
    return combo
end

function CreateValueLabel(parent, option)
    local text = ''
    
    for index, choice in option.choices do
        if selectedOptions[option.key] == choice.key then
                text = choice.text
            break
        end
    end
    
    local label = UIUtil.CreateText(parent, text, 14, "Arial")
    
    label.HandleEvent = function(self, event)
        if event.Type == 'MouseEnter' then
            Tooltip.CreateMouseoverDisplay(self, 'koth_' .. option.key, .5, true)
        elseif event.Type == 'MouseExit' then
            Tooltip.DestroyMouseoverDisplay()
        end
    end
    
    Tooltips['koth_' .. option.key] = { title = option.title, description = option.tooltip }
    
    return label
end

function AddOptionRow(grid, option, editable)
    local background = Bitmap(grid, UIUtil.SkinnableFile('/dialogs/options-02/content-box_bmp.dds'))
    
    background._label = CreateOptionLabel(background, option)
    LayoutHelpers.AtLeftTopIn(background._label, background, 9, 6)

    if editable then
        background._control = CreateValueComboBox(grid, option)
    else
        background._control = CreateValueLabel(background, option)
    end
    
    -- this is here to help position the control
    --TODO get this data from layout!
    local controlGroup = Group(background)
    LayoutHelpers.AtLeftTopIn(controlGroup, background, 338, 5)
    controlGroup.Width:Set(252)
    controlGroup.Height:Set(24)
    
    if background._control then
        LayoutHelpers.AtCenterIn(background._control, controlGroup)
    end
    
    background._control:Show()
    
    dialogControls[option.key] = background._control
        
    return background
end

function CreateDialog()    
    local parent = UIUtil.CreateScreenGroup(GetFrame(0), "KotH Options ScreenGroup")
    local dialog = false
    
    local DismissDialog = function()
        SimCallback({ Func = 'SetKothOptions', Args = selectedOptions })
        parent:Destroy()
        PauseGame(false)
    end

    -- Put the dialog on top
    parent.Depth:Set(GetFrame(0):GetTopmostDepth() + 1)
        
    dialog = Bitmap(parent, UIUtil.SkinnableFile('/dialogs/options-02/panel_bmp.dds'))
    LayoutHelpers.AtCenterIn(dialog, parent)
    
    local title = UIUtil.CreateText(dialog, "King of the Hill Options", 20, UIUtil.titleFont)
    LayoutHelpers.RelativeTo(title, dialog, UIUtil.SkinnableFile('/dialogs/options-02/options-02_layout.lua'), 'l_main_menu_text', 'panel_bmp')
    
    if IsHost() then
        local okButton = UIUtil.CreateButtonStd(dialog, '/widgets02/small', "<LOC _Ok>", 14, 0, 0, "UI_Opt_Yes_No", "UI_Opt_Affirm_Over")
        LayoutHelpers.AtRightTopIn(okButton, dialog, 30, 535)
        
        -- set up button logic
        okButton.OnClick = function(self, modifiers)
            -- We only need to send one query out, since all players receive all queries
            local queryData = {
                From = GetFocusArmy(),
                To = GetFocusArmy(),
                Name = OPTIONS_DISMISSED_QUERY_NAME,
            }
            UserPlayerQuery.Query(queryData)
            DismissDialog()
        end
    
        UIUtil.MakeInputModal(dialog, function() okButton.OnClick(okButton) end)
    else
        UIUtil.MakeInputModal(dialog)
    end
    
    local elementWidth, elementHeight = GetTextureDimensions(UIUtil.UIFile('/dialogs/options-02/content-box_bmp.dds'))
    local optionGrid = Grid(dialog, elementWidth, elementHeight)
    LayoutHelpers.RelativeTo(optionGrid, dialog, UIUtil.SkinnableFile('/dialogs/options-02/options-02_layout.lua'), 'gameplay_bmp', 'panel_bmp')
    LayoutHelpers.DimensionsRelativeTo(optionGrid, UIUtil.SkinnableFile('/dialogs/options-02/options-02_layout.lua'), 'gameplay_bmp')
    local scrollbar = UIUtil.CreateVertScrollbarFor(optionGrid, -4)
    
    -- remove controls and populate grid
    optionGrid:DeleteAndDestroyAll(true)
    optionGrid:AppendCols(1, true)
    
    for index, option in KothOptions.KothOptionInfo do
        optionGrid:AppendRows(1, true)
        
        local item = AddOptionRow(optionGrid, option, IsHost())
        
        optionGrid:SetItem(item, 1, index, true)
    end
    
    optionGrid:EndBatch()
    
    if not IsHost() then
        UserPlayerQuery.AddQueryListener(OPTION_CHANGED_QUERY_NAME, function(data)
            LOG('Received query data: ' .. repr(data))
            if data.Key and dialogControls[data.Key] and data.Value then
            
                selectedOptions[data.Key] = data.Value
        
                for index, option in KothOptions.KothOptionInfo do
                    if option.key == data.Key then
                        for index, choice in option.choices do
                            if choice.key == data.Value then
                                dialogControls[data.Key]:SetText(choice.text)
                            end
                        end
                        
                        break
                    end
                end
                
                WARN("Couldn't find option or choice in the query data")
            else
                WARN('Missing key or index in query data')
            end
        end)
        
        UserPlayerQuery.AddQueryListener(OPTIONS_DISMISSED_QUERY_NAME, function(data)
            LOG('Received query data: ' .. repr(data))
            
            DismissDialog()
        end)
    end
    
    return dialog
end
    